/*
 * HttpConn.h
 *
 *   Created on: 2010-2-11     
 *  Description: 
 *    Copyright: 2010 @ ICT Li Heyuan
 */

#ifndef HTTPCONN_H_
#define HTTPCONN_H_

#include "Conn.h"
#include "../server/Server.h"
#include "../util/Ptr.h"

class HttpConn: public Conn
{
public:
	HttpConn(Server* server, int sock, const EasyAddr &addr);
	virtual ~HttpConn();

	/* @param event TcpServer的事件类型
	 * @return 是否需要epoll继续监视
	 */
	virtual bool handle(unsigned int event);

	//智能指针需要
	const char* GetClassName() const
	{
		return "HttpConn";
	}

protected:

	/* 读取Http请求，以Content-Length的长度为结尾判断
	 * @return epoll是否继续监视
	 */
	bool handle_read();

	/* 执行在Server注册的rpcMethod
	 * @return epoll是否继续监视
	 */
	void handle_execute();

	/* 写回Http包装的json_rpc response
	 * @return epoll是否继续监视
	 */
	bool handle_write();

	/* JobPoll执行method后，callback这里，进行response前最后的处理并转入STAGE_WRITE或STAGE_FINISH
	 */
	void handle_execute_finish();

	/* 当request或者request出错的时候，返回出错的HTTP response
	 * @param 错误的response代码，可以是400或者500
	 */
	void handle_http_error(unsigned int code, const string &msg,
			const string &data);

	/* 构造一个Http response
	 * @return 返回的response
	 */
	string make_http_resp(unsigned int code, const string &msg,
			const string & data);

	/* 从HTTP头中分离出Content-Type
	 * @return Content-Type的数值
	 */
	unsigned long find_Content_Length();

	/* 找DATA区域的开始
	 * @return DATA区域开始的下标
	 */
	string::size_type find_Data_Start();

protected:

	//记录当前的状态,见状态机
	unsigned int _stage;

	//状态机
	enum
	{
		STAGE_READ,
		STAGE_READ_HEAD,
		STAGE_READ_CONTENT,
		STAGE_EXECUTE,
		STAGE_WRITE,
		STAGE_FINISH
	};

	//HTTP的返回状态
	enum
	{
		HTTP_OK = 200, HTTP_400 = 400, HTTP_500 = 500
	};

	//HTTP对应的错误信息
	static string HTTP_MSG_200;
	static string HTTP_MSG_400;
	static string HTTP_MSG_500;

	//读缓存
	std::string _rcvBuf;
	//DATA区域的开始
	unsigned long _contentLen;
	//写缓存
	std::string _sendBuf;
	//还剩余多少要写入
	unsigned long _nSendLeft;
};

#endif /* HTTPCONN_H_ */
